/*
 * Exploder
 * 
 * Tero Pyylampi (218437), Jussi Tuurinkoski (211594)
 *
 * Level Editor scene
 */

#include "EditorScene.h"
#include "EditorLayer.h"
#include "EditorLayerInterface.h"
#include "../MainEngine.h"
#include "../Common.h"
#include "../game/GameCamera.h"
#include "../game/objects/physicobjects/GamePhysicObjectEngine.h"
#include "../game/objects/physicobjects/elements/GameConstructionElement.h"
#include "../game/layers/LayerBackground.h"

using namespace cocos2d;

// default constructor
EditorScene::EditorScene( MainEngine *mainEngine ) : CCScene(), 
	mMainEngine( mainEngine ), mEditorLayer( 0 ), mEditorLayerBackground( 0 ), mEditorLayerInterface( 0 ) {
	initScene();
}

// default destructor
EditorScene::~EditorScene() {
	// TODO: clean up
}

// initialize this scene
void EditorScene::initScene() {
	// create the parallax node for layers
	mParallaxNode = CCParallaxNode::node();
	mParallaxNode->setContentSize( CCSize( WIN_WIDTH, WIN_HEIGHT ) );
	mParallaxNode->setAnchorPoint( ccp( 0.5f, 0.5f ) );
	mParallaxNode->setPosition( WIN_WIDTH / 2.0f, WIN_HEIGHT / 2.0f );

	// create camera
	mGameCamera = new GameCamera( mParallaxNode );

	// create editor layer
	mEditorLayer = new EditorLayer( this );
	// create background layer
	mEditorLayerBackground = new LayerBackground( this );

	// add items to parallax node
	mParallaxNode->addChild( mEditorLayerBackground, Z_LAYER_BACKGROUND, ccp( 0.5f, 0.25f ), ccp( WIN_WIDTH / 4.0f, WIN_HEIGHT * 0.39f ) ); 
	mParallaxNode->addChild( mEditorLayer, Z_LAYER_GAME_BACK, ccp( 1.0f, 1.0f ), ccp( 0, 0 ) ); 

	// add parallax node as a child
	addChild( mParallaxNode );

	// create interface
	mEditorLayerInterface = new EditorLayerInterface( this );
	addChild( mEditorLayerInterface );

	// start updating this scene
	scheduleUpdate();
}

// update -function
void EditorScene::update( cocos2d::ccTime dt ) {
	mGameCamera->update( dt );
	mEditorLayer->update( dt );
	mEditorLayerBackground->update( dt );
	mEditorLayerInterface->update( dt );
}

// create a new empty level
void EditorScene::createNewLevel() {
	// initialize everything
}

// save current level (asks for filename if name = 0)
void EditorScene::saveCurrentLevel( char *fileName ) {
	// open file for editing
	ofstream fileStream;
	fileStream.open( fileName == 0 ? "level.lua" : fileName );

	// save created objects
	fileStream << "function init()" << std::endl;
	savePhysicObjectsIntoFile( fileStream );
	fileStream << "end" << std::endl;

	// create update function
	fileStream << "function update( dt )" << std::endl << "end" << std::endl;

	// close file
	fileStream.close();
}

// load wanted level (asks for filename if name = 0)
void EditorScene::loadLevel( char *fileName ) {
	// TODO
}

// exit the editor and return to menu
void EditorScene::exitEditor() {
	mMainEngine->sceneFinishedExecution();
}

// get main engine
MainEngine *EditorScene::getMainEngine() {
	return mMainEngine;
}

// get camera
GameCamera *EditorScene::getGameCamera() {
	return mGameCamera;
}

// get editor layer
EditorLayer *EditorScene::getEditorLayer() {
	return mEditorLayer;
}

// get interface layer
EditorLayerInterface *EditorScene::getInterfaceLayer() {
	return mEditorLayerInterface;
}

// saves objects into a file
void EditorScene::savePhysicObjectsIntoFile( ofstream &file ) {
	std::vector< GamePhysicObject* > *objects = mEditorLayer->getPhysicObjectEngine()->getPhysicObjects();

	// loop through objects
	for( unsigned int i = 0; i < objects->size(); ++i ) {
		if( objects->at( i )->getObjectType() != ELEMENT_GROUND )
			file << "\tcreateConstructionElement( "
				<< static_cast< int >( dynamic_cast< GameConstructionElement* >( objects->at( i ) )->getElementStateType() ) << ", "
				<< objects->at( i )->getBodyObjects()->at( 0 )->GetPosition().x << ", "
				<< objects->at( i )->getBodyObjects()->at( 0 )->GetPosition().y << ", "
				<< objects->at( i )->getBodyObjects()->at( 0 )->GetAngle() << ", "
				<< static_cast< int >( objects->at( i )->getObjectType() ) << " );" 
				<< std::endl;
	}
}
